package com.ken.common.sentinel.applicaiton;

import com.alibaba.csp.sentinel.cluster.ClusterStateManager;
import com.alibaba.csp.sentinel.cluster.flow.rule.ClusterFlowRuleManager;
import com.alibaba.csp.sentinel.cluster.flow.rule.ClusterParamFlowRuleManager;
import com.alibaba.csp.sentinel.cluster.server.config.ClusterServerConfigManager;
import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource;
import com.alibaba.csp.sentinel.property.SentinelProperty;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.ken.common.sentinel.config.SentinelNacosProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;

import java.util.List;
import java.util.Set;

/**
 * Sentinel集群流服务端配置类
 */
public class SentinelClusterServerConfiguration implements CommandLineRunner {

    /**
     * 注入配置信息
     */
    @Autowired
    private SentinelNacosProperties sentinelNacosProperties;

    @Override
    public void run(String... args) throws Exception {
        System.out.println("Sentinel服务端初始化！！！！");

        //配置为服务端
        ClusterStateManager.applyState(ClusterStateManager.CLUSTER_SERVER);

        //配置动态的规则数据源
        ClusterFlowRuleManager.setPropertySupplier(namespace -> {
            System.out.println("namespace:" + namespace);
            ReadableDataSource<String, List<FlowRule>> ds = new NacosDataSource<>(
                    sentinelNacosProperties.getServerProperties(),
                    sentinelNacosProperties.getGroupId(),
                    namespace + sentinelNacosProperties.getFlowRulePrefix(),
                    source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {}));
            SentinelProperty<List<FlowRule>> property = ds.getProperty();
            return property;
        });

        //配置动态的参数规则数据源
        ClusterParamFlowRuleManager.setPropertySupplier(namespace -> {
            System.out.println("namespace:" + namespace);
            ReadableDataSource<String, List<ParamFlowRule>> ds = new NacosDataSource<>(
                    sentinelNacosProperties.getServerProperties(),
                    sentinelNacosProperties.getGroupId(),
                    namespace + sentinelNacosProperties.getFlowParamRulePrefix(),
                    source -> JSON.parseObject(source, new TypeReference<List<ParamFlowRule>>() {}));
            SentinelProperty<List<ParamFlowRule>> property = ds.getProperty();
            return property;
        });

        //配置动态的命名空间数据源 -- 必须放在最后
        ReadableDataSource<String, Set<String>> namespaceDs = new NacosDataSource<>(
                sentinelNacosProperties.getServerProperties(),
                sentinelNacosProperties.getGroupId(),
                sentinelNacosProperties.getNamespaceSetDataId(),
                source -> JSON.parseObject(source, new TypeReference<Set<String>>() {}));
        ClusterServerConfigManager.registerNamespaceSetProperty(namespaceDs.getProperty());
    }
}
